from cryptography import x509
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.serialization import pkcs7
from cryptography.hazmat.backends import default_backend


def create_signed_pkcs7(data_to_sign, cert_file, private_key_file, output_path):
    """
    创建带签名的PKCS#7数据

    参数:
    - data_to_sign: 要签名的数据（字节类型）
    - cert_file: 签名者证书路径
    - private_key_file: 签名者私钥路径
    - output_path: 输出的PKCS#7签名文件路径
    """
    # 加载证书和私钥
    with open(cert_file, 'rb') as f:
        cert = x509.load_pem_x509_certificate(f.read(), default_backend())

    with open(private_key_file, 'rb') as f:
        private_key = serialization.load_pem_private_key(
            f.read(), password=None, backend=default_backend()
        )

    # 创建PKCS#7签名构建器
    builder = pkcs7.PKCS7SignatureBuilder().set_data(data_to_sign)

    # 添加证书和签名
    builder = builder.add_signer(
        cert,  # 直接传入证书，而非使用关键字参数
        private_key,
        hashes.SHA256()
    )

    # 生成带签名的PKCS#7，使用openssl pkcs7 -inform pem -in signed_data.p7s -print_certs
    signed_pkcs7 = builder.sign(
        encoding=serialization.Encoding.PEM,
        options=[pkcs7.PKCS7Options.DetachedSignature],
        backend=default_backend()
    )

    # 保存签名结果
    with open(output_path, 'wb') as f:
        f.write(signed_pkcs7)

    print(f"带签名的PKCS#7已生成: {output_path}")


# 示例使用
if __name__ == "__main__":
    # 要签名的数据
    data_to_sign = b"Hello, this is a signed message."

    # 签名者证书和私钥
    cert_file = "certificate.pem"
    private_key_file = "private_key.pem"

    # 输出路径
    output_path = "signed_data.p7s"

    # 创建带签名的PKCS#7
    create_signed_pkcs7(data_to_sign, cert_file, private_key_file, output_path)